<!DOCTYPE html>
<html lang="en">
  <head>
    <title>three.js webgl - lights - hemisphere light</title>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
    />
    <link type="text/css" rel="stylesheet" href="main.css" />
    <style>
      body {
        color: #444;
      }
      a {
        color: #08f;
      }
    </style>
  </head>
  <body>
    <div id="container"></div>
    <div id="info">
      <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a>
      - webgl hemisphere light example<br />
      flamingo by
      <a href="https://mirada.com/" target="_blank" rel="noopener">mirada</a>
      from <a href="http://www.ro.me" target="_blank" rel="noopener">ro.me</a>
    </div>

    <script type="importmap">
      {
        "imports": {
          "three": "/node_modules/three/build/three.module.js",
          "three/addons/": "/node_modules/three/examples/jsm/"
        }
      }
    </script>

    <script type="module">
      import * as THREE from "three";

      import { GUI } from "three/addons/libs/lil-gui.module.min.js";

      import { OrbitControls } from "three/addons/controls/OrbitControls.js";
      import { RGBELoader } from "three/addons/loaders/RGBELoader.js";
      import { LightProbeGenerator } from "three/addons/lights/LightProbeGenerator.js";

      let mesh, renderer, scene, camera;

      let gui;

      let lightProbe;
      let directionalLight;

      // linear color space
      const API = {
        lightProbeIntensity: 1.0,
        directionalLightIntensity: 0.6,
        envMapIntensity: 1,
      };

      init();

      function init() {
        // renderer
        renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        // tone mapping
        renderer.toneMapping = THREE.NoToneMapping;

        // scene
        scene = new THREE.Scene();

        // camera
        camera = new THREE.PerspectiveCamera(
          40,
          window.innerWidth / window.innerHeight,
          1,
          1000
        );
        camera.position.set(0, 0, 30);

        // controls
        const controls = new OrbitControls(camera, renderer.domElement);
        controls.addEventListener("change", render);
        controls.minDistance = 10;
        controls.maxDistance = 500;
        // controls.enablePan = false;

        // probe
        lightProbe = new THREE.LightProbe();
        scene.add(lightProbe);

        // light
        directionalLight = new THREE.DirectionalLight(
          0xffffff,
          API.directionalLightIntensity
        );
        directionalLight.position.set(10, 10, 10).normalize();
        scene.add(directionalLight);

        // envmap
        const genCubeUrls = function (prefix, postfix) {
          return [
            prefix + "px" + postfix,
            prefix + "nx" + postfix,
            prefix + "py" + postfix,
            prefix + "ny" + postfix,
            prefix + "pz" + postfix,
            prefix + "nz" + postfix,
          ];
        };

        const urls = genCubeUrls("textures/cube/skyboxsun25deg/", ".jpg");

        const rgbeLoader = new RGBELoader();
        rgbeLoader.load(
          "./rosendal_park_sunset_puresky_1k.hdr",
          // new THREE.CubeTextureLoader().load(urls
          function (cubeTexture) {
            scene.background = cubeTexture;
            cubeTexture.mapping = THREE.EquirectangularReflectionMapping;

            // lightProbe.copy(LightProbeGenerator.fromCubeTexture(cubeTexture));

            const geometry = new THREE.SphereGeometry(5, 64, 32);
            //const geometry = new THREE.TorusKnotGeometry( 4, 1.5, 256, 32, 2, 3 );

            const material = new THREE.MeshPhysicalMaterial({
              color: 0xaaaaaa,
              metalness: 0.9,
              roughness: 0,
              opacity: 0.5,
              transparent: true,
              envMap: cubeTexture,
              envMapIntensity: API.envMapIntensity,
            });

            // mesh
            mesh = new THREE.Mesh(geometry, material);
            mesh.position.set(0, 10, 0);
            scene.add(mesh);

            render();
          }
        );

        // gui
        gui = new GUI({ title: "Intensity" });

        gui
          .add(API, "lightProbeIntensity", 0, 1, 0.02)
          .name("light probe")
          .onChange(function () {
            lightProbe.intensity = API.lightProbeIntensity;
            render();
          });

        gui
          .add(API, "directionalLightIntensity", 0, 1, 0.02)
          .name("directional light")
          .onChange(function () {
            directionalLight.intensity = API.directionalLightIntensity;
            render();
          });

        gui
          .add(API, "envMapIntensity", 0, 1, 0.02)
          .name("envMap")
          .onChange(function () {
            mesh.material.envMapIntensity = API.envMapIntensity;
            render();
          });

        // listener
        window.addEventListener("resize", onWindowResize);
      }

      function onWindowResize() {
        renderer.setSize(window.innerWidth, window.innerHeight);

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        render();
      }

      function render() {
        renderer.render(scene, camera);
      }
    </script>
  </body>
</html>
